{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 程序说明\n",
    "时间：2016年11月16日\n",
    "\n",
    "说明：说明：这是一个使用卷积网络在CIFAR10数据集上做分类的程序，其中使用了数据增强。\n",
    "\n",
    "数据集：CIFAR10"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.加载keras模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Using TensorFlow backend.\n"
     ]
    }
   ],
   "source": [
    "from __future__ import print_function\n",
    "from keras.datasets import cifar10\n",
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense, Dropout, Activation, Flatten\n",
    "from keras.layers import Convolution2D, MaxPooling2D\n",
    "from keras.optimizers import SGD\n",
    "from keras.utils import np_utils"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.变量初始化"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size = 32\n",
    "nb_classes = 10\n",
    "nb_epoch = 20\n",
    "data_augmentation = True\n",
    "\n",
    "# input image dimensions\n",
    "img_rows, img_cols = 32, 32\n",
    "# the CIFAR10 images are RGB\n",
    "img_channels = 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.准备数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X_train shape: (50000, 32, 32, 3)\n",
      "50000 train samples\n",
      "10000 test samples\n"
     ]
    }
   ],
   "source": [
    "# the data, shuffled and split between train and test sets\n",
    "(X_train, y_train), (X_test, y_test) = cifar10.load_data()\n",
    "print('X_train shape:', X_train.shape)\n",
    "print(X_train.shape[0], 'train samples')\n",
    "print(X_test.shape[0], 'test samples')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 转换类标号"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# convert class vectors to binary class matrices\n",
    "Y_train = np_utils.to_categorical(y_train, nb_classes)\n",
    "Y_test = np_utils.to_categorical(y_test, nb_classes)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4.建立模型\n",
    "### 使用Sequential（）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "model = Sequential()\n",
    "\n",
    "model.add(Convolution2D(32, 3, 3, border_mode='same',\n",
    "                        input_shape=X_train.shape[1:]))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Convolution2D(32, 3, 3))\n",
    "model.add(Activation('relu'))\n",
    "model.add(MaxPooling2D(pool_size=(2, 2)))\n",
    "model.add(Dropout(0.25))\n",
    "\n",
    "model.add(Convolution2D(64, 3, 3, border_mode='same'))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Convolution2D(64, 3, 3))\n",
    "model.add(Activation('relu'))\n",
    "model.add(MaxPooling2D(pool_size=(2, 2)))\n",
    "model.add(Dropout(0.25))\n",
    "\n",
    "model.add(Flatten())\n",
    "model.add(Dense(512))\n",
    "model.add(Activation('relu'))\n",
    "model.add(Dropout(0.5))\n",
    "model.add(Dense(nb_classes))\n",
    "model.add(Activation('softmax'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 打印模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "____________________________________________________________________________________________________\n",
      "Layer (type)                     Output Shape          Param #     Connected to                     \n",
      "====================================================================================================\n",
      "convolution2d_1 (Convolution2D)  (None, 32, 32, 32)    896         convolution2d_input_1[0][0]      \n",
      "____________________________________________________________________________________________________\n",
      "activation_1 (Activation)        (None, 32, 32, 32)    0           convolution2d_1[0][0]            \n",
      "____________________________________________________________________________________________________\n",
      "convolution2d_2 (Convolution2D)  (None, 30, 30, 32)    9248        activation_1[0][0]               \n",
      "____________________________________________________________________________________________________\n",
      "activation_2 (Activation)        (None, 30, 30, 32)    0           convolution2d_2[0][0]            \n",
      "____________________________________________________________________________________________________\n",
      "maxpooling2d_1 (MaxPooling2D)    (None, 15, 15, 32)    0           activation_2[0][0]               \n",
      "____________________________________________________________________________________________________\n",
      "dropout_1 (Dropout)              (None, 15, 15, 32)    0           maxpooling2d_1[0][0]             \n",
      "____________________________________________________________________________________________________\n",
      "convolution2d_3 (Convolution2D)  (None, 15, 15, 64)    18496       dropout_1[0][0]                  \n",
      "____________________________________________________________________________________________________\n",
      "activation_3 (Activation)        (None, 15, 15, 64)    0           convolution2d_3[0][0]            \n",
      "____________________________________________________________________________________________________\n",
      "convolution2d_4 (Convolution2D)  (None, 13, 13, 64)    36928       activation_3[0][0]               \n",
      "____________________________________________________________________________________________________\n",
      "activation_4 (Activation)        (None, 13, 13, 64)    0           convolution2d_4[0][0]            \n",
      "____________________________________________________________________________________________________\n",
      "maxpooling2d_2 (MaxPooling2D)    (None, 6, 6, 64)      0           activation_4[0][0]               \n",
      "____________________________________________________________________________________________________\n",
      "dropout_2 (Dropout)              (None, 6, 6, 64)      0           maxpooling2d_2[0][0]             \n",
      "____________________________________________________________________________________________________\n",
      "flatten_1 (Flatten)              (None, 2304)          0           dropout_2[0][0]                  \n",
      "____________________________________________________________________________________________________\n",
      "dense_1 (Dense)                  (None, 512)           1180160     flatten_1[0][0]                  \n",
      "____________________________________________________________________________________________________\n",
      "activation_5 (Activation)        (None, 512)           0           dense_1[0][0]                    \n",
      "____________________________________________________________________________________________________\n",
      "dropout_3 (Dropout)              (None, 512)           0           activation_5[0][0]               \n",
      "____________________________________________________________________________________________________\n",
      "dense_2 (Dense)                  (None, 10)            5130        dropout_3[0][0]                  \n",
      "____________________________________________________________________________________________________\n",
      "activation_6 (Activation)        (None, 10)            0           dense_2[0][0]                    \n",
      "====================================================================================================\n",
      "Total params: 1250858\n",
      "____________________________________________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5.训练与评估\n",
    "### 编译模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# let's train the model using SGD + momentum (how original).\n",
    "sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)\n",
    "model.compile(loss='categorical_crossentropy',\n",
    "              optimizer=sgd,\n",
    "              metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数据压缩为0~1之间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "X_train = X_train.astype('float32')\n",
    "X_test = X_test.astype('float32')\n",
    "X_train /= 255\n",
    "X_test /= 255\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数据增强\n",
    "数据增强使用的ImageDataGenerator这个函数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Using real-time data augmentation.\n",
      "Epoch 1/20\n",
      "50000/50000 [==============================] - 37s - loss: 2.3037 - acc: 0.1010 - val_loss: 2.3034 - val_acc: 0.1000\n",
      "Epoch 2/20\n",
      "50000/50000 [==============================] - 37s - loss: 2.3035 - acc: 0.0991 - val_loss: 2.3033 - val_acc: 0.1000\n",
      "Epoch 3/20\n",
      "50000/50000 [==============================] - 38s - loss: 2.3034 - acc: 0.0977 - val_loss: 2.3030 - val_acc: 0.1000\n",
      "Epoch 4/20\n",
      "50000/50000 [==============================] - 36s - loss: 2.3035 - acc: 0.0975 - val_loss: 2.3036 - val_acc: 0.1000\n",
      "Epoch 5/20\n",
      "50000/50000 [==============================] - 37s - loss: 2.3035 - acc: 0.0986 - val_loss: 2.3028 - val_acc: 0.1000\n",
      "Epoch 6/20\n",
      "50000/50000 [==============================] - 36s - loss: 2.3034 - acc: 0.0991 - val_loss: 2.3031 - val_acc: 0.1000\n",
      "Epoch 7/20\n",
      "50000/50000 [==============================] - 37s - loss: 2.3033 - acc: 0.1004 - val_loss: 2.3030 - val_acc: 0.1000\n",
      "Epoch 8/20\n",
      "50000/50000 [==============================] - 38s - loss: 2.3035 - acc: 0.0970 - val_loss: 2.3029 - val_acc: 0.1000\n",
      "Epoch 9/20\n",
      "50000/50000 [==============================] - 36s - loss: 2.3034 - acc: 0.0980 - val_loss: 2.3034 - val_acc: 0.1000\n",
      "Epoch 10/20\n",
      "50000/50000 [==============================] - 37s - loss: 2.3033 - acc: 0.0989 - val_loss: 2.3032 - val_acc: 0.1000\n",
      "Epoch 11/20\n",
      "50000/50000 [==============================] - 37s - loss: 2.3034 - acc: 0.0983 - val_loss: 2.3028 - val_acc: 0.1000\n",
      "Epoch 12/20\n",
      "50000/50000 [==============================] - 36s - loss: 2.3033 - acc: 0.0997 - val_loss: 2.3029 - val_acc: 0.1000\n",
      "Epoch 13/20\n",
      "50000/50000 [==============================] - 37s - loss: 2.3033 - acc: 0.1009 - val_loss: 2.3032 - val_acc: 0.1000\n",
      "Epoch 14/20\n",
      "50000/50000 [==============================] - 37s - loss: 2.3035 - acc: 0.0995 - val_loss: 2.3029 - val_acc: 0.1000\n",
      "Epoch 15/20\n",
      "50000/50000 [==============================] - 36s - loss: 2.3034 - acc: 0.0955 - val_loss: 2.3029 - val_acc: 0.1000\n",
      "Epoch 16/20\n",
      "50000/50000 [==============================] - 38s - loss: 2.3034 - acc: 0.0995 - val_loss: 2.3028 - val_acc: 0.1000\n",
      "Epoch 17/20\n",
      "50000/50000 [==============================] - 36s - loss: 2.3035 - acc: 0.0955 - val_loss: 2.3030 - val_acc: 0.1000\n",
      "Epoch 18/20\n",
      "50000/50000 [==============================] - 38s - loss: 2.3033 - acc: 0.0977 - val_loss: 2.3039 - val_acc: 0.1000\n",
      "Epoch 19/20\n",
      "50000/50000 [==============================] - 38s - loss: 2.3035 - acc: 0.0989 - val_loss: 2.3031 - val_acc: 0.1000\n",
      "Epoch 20/20\n",
      "50000/50000 [==============================] - 36s - loss: 2.3033 - acc: 0.0979 - val_loss: 2.3033 - val_acc: 0.1000\n"
     ]
    }
   ],
   "source": [
    "if not data_augmentation:\n",
    "    print('Not using data augmentation.')\n",
    "    model.fit(X_train, Y_train,\n",
    "              batch_size=batch_size,\n",
    "              nb_epoch=nb_epoch,\n",
    "              validation_data=(X_test, Y_test),\n",
    "              shuffle=True)\n",
    "else:\n",
    "    print('Using real-time data augmentation.')\n",
    "\n",
    "    # 这将做预处理和实时数据增加\n",
    "    datagen = ImageDataGenerator(\n",
    "        featurewise_center=False,  # 在数据集上将输入平均值设置为0\n",
    "        samplewise_center=False,  # 将每个样本均值设置为0\n",
    "        featurewise_std_normalization=False,  # 将输入除以数据集的std\n",
    "        samplewise_std_normalization=False,  # 将每个输入除以其std\n",
    "        zca_whitening=False,  # 应用ZCA白化\n",
    "        rotation_range=0,  # 在一个范围下随机旋转图像(degrees, 0 to 180)\n",
    "        width_shift_range=0.1,  # 水平随机移位图像（总宽度的分数）\n",
    "        height_shift_range=0.1,  # 随机地垂直移动图像（总高度的分数）\n",
    "        horizontal_flip=True,  # 随机翻转图像\n",
    "        vertical_flip=False)  # 随机翻转图像\n",
    "\n",
    "    # 计算特征方向归一化所需的数量\n",
    "    # (std, mean, and principal components if ZCA whitening is applied)\n",
    "    datagen.fit(X_train)\n",
    "\n",
    "    # fit the model on the batches generated by datagen.flow()\n",
    "    model.fit_generator(datagen.flow(X_train, Y_train,\n",
    "                        batch_size=batch_size),\n",
    "                        samples_per_epoch=X_train.shape[0],\n",
    "                        nb_epoch=nb_epoch,\n",
    "                        validation_data=(X_test, Y_test))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.12"
  },
  "ssap_exp_config": {
   "error_alert": "Error Occurs!",
   "initial": [],
   "max_iteration": 1000,
   "recv_id": "",
   "running": [],
   "summary": [],
   "version": "1.1.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
